grammar Hobbes2008;

options {
	language = Java;
	output=AST;
}

tokens {
  TUPLE;
  APPLICATION;
  IF='if';
  ELSE='else';
  THEN='then';
  END='end';
  LET='let';
  IN='in';
  KEYWORD=':=';
  LETFUNC='letfunc';
}

@header {
package edu.calvin.djs32.cs214.interpreters.frontend;
}

@lexer::header {
package edu.calvin.djs32.cs214.interpreters.frontend;

}
@members { 
  protected void mismatch(IntStream input, int ttype, BitSet follow) 
    throws RecognitionException { 
    throw new MismatchedTokenException(ttype, input); 
  } 
  public void recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) 
    throws RecognitionException { 
    throw e; 
  } 
} 
@rulecatch { 
  catch (RecognitionException e) { 
    throw e; 
  } 
} 
@lexer::members { 
  protected void mismatch(IntStream input, int ttype, BitSet follow) 
    throws RecognitionException { 
    throw new MismatchedTokenException(ttype, input); 
  } 
  public void recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) 
    throws RecognitionException { 
    throw e; 
  } 
  public void recover(RecognitionException re) {
    throw new RuntimeException(re);
  }
}

program: expression EOF! ;

fragment
NUMBER : '0'..'9';

fragment
HEXDIGIT:(NUMBER)|(('a'..'f')|('A'..'F'));

fragment
SIGN	:	('+'|'-');
	
INTEGER 	:	((SIGN)? (NUMBER)+)|((SIGN)? '0x'(HEXDIGIT)(HEXDIGIT)(HEXDIGIT)(HEXDIGIT));
IDENTIFIER  	: ('*'|'+'|'-'|'/'|'a'..'z'|'!'|'<'|'<='|'='|'!='|'>'|'>='|'A'..'Z')*;

WHITESPACE
                : (' '|'\t'|'\n'|'\r')
                { skip(); }
                ;
                
COMMENTS
                : ((('/*').*('*/'))|(('//').*('\n'))) 
                { skip(); }
                ;
                
STRING 	:	('\'')~('\'')*('\'');
COMMA : ',' ;
LPAREN	:	'(';
RPAREN	:	')'; 

expression 	:       INTEGER | STRING | tuple | application | ife | identifier | let | letfunc;
application	:	identifier tuple -> ^(APPLICATION identifier tuple);
identifier	:	IDENTIFIER;
let		:	LET identifier KEYWORD expression IN expression -> ^(LET identifier expression expression);
ife		:	IF expression THEN expression ELSE expression END -> ^(IF expression*);
tuple		:	LPAREN (expression (COMMA expression)*)? RPAREN -> ^(TUPLE (expression)*);
letfunc		:	LETFUNC identifier identifier KEYWORD expression IN expression -> ^(LETFUNC identifier identifier expression expression);
